﻿module CoreTests.JSONGen.Chart2D

open Expecto
open Plotly.NET
open Plotly.NET.LayoutObjects
open Plotly.NET.TraceObjects


open TestUtils.JsonGen
open Chart2DTestCharts

module Scatter =
    [<Tests>]
    let ``Scatter chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Scatter" [
            ]
        ]

module Point =
    [<Tests>]
    let ``Point chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Point" [
                testCase "toJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"points","mode":"markers+text","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"text":["a","b","c","d","e","f","g","h","i","j"],"textposition":"top right","marker":{},"line":{}}],"layout":{},"config":{}}"""
                    |> jsonIs Point.``Point chart with text labels``
                )
                testCase "toFigureJson" ( fun () ->
                   """{"data":[{"type":"scatter","name":"points","mode":"markers+text","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"text":["a","b","c","d","e","f","g","h","i","j"],"textposition":"top right","marker":{},"line":{}}],"layout":{},"frames":[]}"""
                   |> figureJsonIs Point.``Point chart with text labels``
                )
            ]
        ]

module Line =
    [<Tests>]
    let ``Line chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Line" [
                testCase "With LineStyle toJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"line","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{"symbol":"1"},"line":{"width":2.0,"dash":"dot"}}],"layout":{},"config":{}}"""
                    |> jsonIs Line.``Line chart with line styling``
                )
                testCase "With LineStyle toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"line","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{"symbol":"1"},"line":{"width":2.0,"dash":"dot"}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Line.``Line chart with line styling``
                )
                testCase "Chart line toJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0,33.0,34.0,35.0,36.0,37.0,38.0,39.0,40.0,41.0,42.0,43.0,44.0,45.0,46.0,47.0,48.0,49.0,50.0,51.0,52.0,53.0,54.0,55.0,56.0,57.0,58.0,59.0,60.0,61.0,62.0,63.0,64.0,65.0,66.0,67.0,68.0,69.0,70.0,71.0,72.0,73.0,74.0,75.0,76.0,77.0,78.0,79.0,80.0,81.0,82.0,83.0,84.0,85.0,86.0,87.0,88.0,89.0,90.0,91.0,92.0,93.0,94.0,95.0,96.0,97.0,98.0,99.0,100.0],"y":[1.0,4.0,9.0,16.0,25.0,36.0,49.0,64.0,81.0,100.0,121.0,144.0,169.0,196.0,225.0,256.0,289.0,324.0,361.0,400.0,441.0,484.0,529.0,576.0,625.0,676.0,729.0,784.0,841.0,900.0,961.0,1024.0,1089.0,1156.0,1225.0,1296.0,1369.0,1444.0,1521.0,1600.0,1681.0,1764.0,1849.0,1936.0,2025.0,2116.0,2209.0,2304.0,2401.0,2500.0,2601.0,2704.0,2809.0,2916.0,3025.0,3136.0,3249.0,3364.0,3481.0,3600.0,3721.0,3844.0,3969.0,4096.0,4225.0,4356.0,4489.0,4624.0,4761.0,4900.0,5041.0,5184.0,5329.0,5476.0,5625.0,5776.0,5929.0,6084.0,6241.0,6400.0,6561.0,6724.0,6889.0,7056.0,7225.0,7396.0,7569.0,7744.0,7921.0,8100.0,8281.0,8464.0,8649.0,8836.0,9025.0,9216.0,9409.0,9604.0,9801.0,10000.0],"marker":{},"line":{}}],"layout":{},"config":{}}"""
                    |> jsonIs Line.``Simple line chart``
                )
                testCase "Chart line toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0,33.0,34.0,35.0,36.0,37.0,38.0,39.0,40.0,41.0,42.0,43.0,44.0,45.0,46.0,47.0,48.0,49.0,50.0,51.0,52.0,53.0,54.0,55.0,56.0,57.0,58.0,59.0,60.0,61.0,62.0,63.0,64.0,65.0,66.0,67.0,68.0,69.0,70.0,71.0,72.0,73.0,74.0,75.0,76.0,77.0,78.0,79.0,80.0,81.0,82.0,83.0,84.0,85.0,86.0,87.0,88.0,89.0,90.0,91.0,92.0,93.0,94.0,95.0,96.0,97.0,98.0,99.0,100.0],"y":[1.0,4.0,9.0,16.0,25.0,36.0,49.0,64.0,81.0,100.0,121.0,144.0,169.0,196.0,225.0,256.0,289.0,324.0,361.0,400.0,441.0,484.0,529.0,576.0,625.0,676.0,729.0,784.0,841.0,900.0,961.0,1024.0,1089.0,1156.0,1225.0,1296.0,1369.0,1444.0,1521.0,1600.0,1681.0,1764.0,1849.0,1936.0,2025.0,2116.0,2209.0,2304.0,2401.0,2500.0,2601.0,2704.0,2809.0,2916.0,3025.0,3136.0,3249.0,3364.0,3481.0,3600.0,3721.0,3844.0,3969.0,4096.0,4225.0,4356.0,4489.0,4624.0,4761.0,4900.0,5041.0,5184.0,5329.0,5476.0,5625.0,5776.0,5929.0,6084.0,6241.0,6400.0,6561.0,6724.0,6889.0,7056.0,7225.0,7396.0,7569.0,7744.0,7921.0,8100.0,8281.0,8464.0,8649.0,8836.0,9025.0,9216.0,9409.0,9604.0,9801.0,10000.0],"marker":{},"line":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Line.``Simple line chart``
                )
            ]
        ]

module Spline =
    [<Tests>]
    let ``Spline chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Spline" [
                testCase "Spline chart toJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"spline","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{"shape":"spline"}}],"layout":{},"config":{}}"""
                    |> jsonIs Spline.``Simple spline chart``
                )
                testCase "Spline chart toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"spline","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{"shape":"spline"}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Spline.``Simple spline chart``
                )
            ]
        ]

module Bubble =
    [<Tests>]
    let ``Bubble chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Bubble" [
                testCase "Bubble toJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"markers","x":[2,4,6],"y":[4,1,6],"marker":{"size":[19,26,55]},"line":{}}],"layout":{},"config":{}}"""
                    |> jsonIs Bubble.``Simple bubble chart``
                )
                testCase "Bubble toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"markers","x":[2,4,6],"y":[4,1,6],"marker":{"size":[19,26,55]},"line":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Bubble.``Simple bubble chart``
                );
            ]
        ]

module Range =
    [<Tests>]
    let ``Range chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Range" [
                testCase "Range plot toJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"lower","showlegend":true,"legendgroup":"Range","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[1.0244410755226578,1.1291130737537114,4.930085632917511,1.4292117752736488,2.5179894182449156,2.3470285278032668,1.5358344954605374,1.4046562835130172,2.6874669190437843,0.7493837949584163],"fillcolor":"lightblue","marker":{"color":"lightblue"}},{"type":"scatter","name":"upper","showlegend":true,"legendgroup":"Range","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.338369840913624,1.7844184475412679,5.2629626417825754,2.125375844363764,3.4634618528482792,3.4283738280312965,2.6463105539541276,2.4505998873853123,4.096133255211699,1.1174599459010455],"fill":"tonexty","fillcolor":"lightblue","marker":{"color":"lightblue"}},{"type":"scatter","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{"color":"grey"},"line":{},"legendgroup":"Range","legendgrouptitle":{"text":"Range"}}],"layout":{},"config":{}}"""
                    |> jsonIs Range.``Styled range chart``
                )
                testCase "Range plot toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","name":"lower","showlegend":true,"legendgroup":"Range","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[1.0244410755226578,1.1291130737537114,4.930085632917511,1.4292117752736488,2.5179894182449156,2.3470285278032668,1.5358344954605374,1.4046562835130172,2.6874669190437843,0.7493837949584163],"fillcolor":"lightblue","marker":{"color":"lightblue"}},{"type":"scatter","name":"upper","showlegend":true,"legendgroup":"Range","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.338369840913624,1.7844184475412679,5.2629626417825754,2.125375844363764,3.4634618528482792,3.4283738280312965,2.6463105539541276,2.4505998873853123,4.096133255211699,1.1174599459010455],"fill":"tonexty","fillcolor":"lightblue","marker":{"color":"lightblue"}},{"type":"scatter","mode":"lines+markers","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{"color":"grey"},"line":{},"legendgroup":"Range","legendgrouptitle":{"text":"Range"}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Range.``Styled range chart``
                );
            ]
        ]

module Area =
    [<Tests>]
    let ``Area chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Area" [
                testCase "Simple area toJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"marker":{},"line":{},"fill":"tozeroy","fillpattern":{}}],"layout":{},"config":{}}"""
                    |> jsonIs Area.``Simple area chart``
                )
                testCase "Simple area toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"marker":{},"line":{},"fill":"tozeroy","fillpattern":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Area.``Simple area chart``
                );
            ]
        ]

module SplineArea =
    [<Tests>]
    let ``SplineArea chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "SplineArea" [
                testCase "SplineArea toJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"marker":{},"line":{"shape":"spline"},"fill":"tozeroy","fillpattern":{}}],"layout":{},"config":{}}"""
                    |> jsonIs SplineArea.``Simple spline area chart``
                )
                testCase "SplineArea toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"marker":{},"line":{"shape":"spline"},"fill":"tozeroy","fillpattern":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs SplineArea.``Simple spline area chart``
                );
            ]
        ]

module StackedArea =
    [<Tests>]
    let ``StackedArea chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "StackedArea" [
                testCase "Stacked area toJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"stackgroup":"stackedarea","marker":{},"line":{},"fill":"tonexty","fillpattern":{}},{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,5.5,4.5,7.5,2.5,5.0,7.5,5.0,2.5,5.0],"stackgroup":"stackedarea","marker":{},"line":{},"fill":"tonexty","fillpattern":{}}],"layout":{},"config":{}}"""
                    |> jsonIs StackedArea.``Two stacked areas chart``
                )
                testCase "Stacked area toFigureJson" ( fun () ->
                    """{"data":[{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,2.5,5.0,7.5,5.0,2.5,7.5,4.5,5.5,5.0],"stackgroup":"stackedarea","marker":{},"line":{},"fill":"tonexty","fillpattern":{}},{"type":"scatter","mode":"lines","x":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[5.0,5.5,4.5,7.5,2.5,5.0,7.5,5.0,2.5,5.0],"stackgroup":"stackedarea","marker":{},"line":{},"fill":"tonexty","fillpattern":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs StackedArea.``Two stacked areas chart``
                );
            ]
        ]

module Funnel =
    [<Tests>]
    let ``Funnel chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Funnel" [
                testCase "Funnel toJson" ( fun () ->
                    """{"data":[{"type":"funnel","x":[1200.0,909.4,600.6,300.0,80.0],"y":["Sales person A","Sales person B","Sales person C","Sales person D","Sales person E"],"marker":{"color":"59D4E8","line":{"color":"3E4E88","width":2.0}},"connector":{"line":{"color":"royalblue","width":3.0,"dash":"dot"}}}],"layout":{"margin":{"l":100}},"config":{}}"""
                    |> jsonIs Funnel.``Simple funnel chart``
                )
                testCase "Funnel toFigureJson" ( fun () ->
                    """{"data":[{"type":"funnel","x":[1200.0,909.4,600.6,300.0,80.0],"y":["Sales person A","Sales person B","Sales person C","Sales person D","Sales person E"],"marker":{"color":"59D4E8","line":{"color":"3E4E88","width":2.0}},"connector":{"line":{"color":"royalblue","width":3.0,"dash":"dot"}}}],"layout":{"margin":{"l":100}},"frames":[]}"""
                    |> figureJsonIs Funnel.``Simple funnel chart``
                );
            ]
        ]

module StackedFunnel =
    [<Tests>]
    let ``StackedFunnel chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "StackedFunnel" [
            ]
        ]

module Waterfall =
    [<Tests>]
    let ``Waterfall chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Waterfall" [
            ]
        ]

module Bar =
    [<Tests>]
    let ``Bar chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Bar" [
                testCase "Bar chart toJson" ( fun () ->
                    """{"data":[{"type":"bar","x":[20,14,23],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}}],"layout":{},"config":{}}"""
                    |> jsonIs Bar.``Simple bar chart``
                )
                testCase "Bar chart toFigureJson" ( fun () ->
                    """{"data":[{"type":"bar","x":[20,14,23],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Bar.``Simple bar chart``
                );
            ]
        ]

module StackedBar =
    [<Tests>]
    let ``StackedBar chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "StackedBar" [
                testCase "Stacked bar toJson" ( fun () ->
                    """{"data":[{"type":"bar","name":"old","x":[20,14,23],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}},{"type":"bar","name":"new","x":[8,21,13],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}}],"layout":{"barmode":"stack"},"config":{}}"""
                    |> jsonIs StackedBar.``Two stacked bars chart``
                )
                testCase "Stacked bar toFigureJson" ( fun () ->
                    """{"data":[{"type":"bar","name":"old","x":[20,14,23],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}},{"type":"bar","name":"new","x":[8,21,13],"y":["Product A","Product B","Product C"],"orientation":"h","marker":{"pattern":{}}}],"layout":{"barmode":"stack"},"frames":[]}"""
                    |> figureJsonIs StackedBar.``Two stacked bars chart``
                );
            ]
        ]

module Column =
    [<Tests>]
    let ``Column chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Column" [
                testCase "Column chart toJson" ( fun () ->
                    """{"data":[{"type":"bar","x":["Product A","Product B","Product C"],"y":[20,14,23],"orientation":"v","marker":{"pattern":{}}}],"layout":{},"config":{}}"""
                    |> jsonIs Column.``Simple column chart``
                )
                testCase "Column chart toFigureJson" ( fun () ->
                    """{"data":[{"type":"bar","x":["Product A","Product B","Product C"],"y":[20,14,23],"orientation":"v","marker":{"pattern":{}}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Column.``Simple column chart``
                );
            ]
        ]

module StackedColumn =
    [<Tests>]
    let ``StackedColumn chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "StackedColumn" [
                testCase "Stacked column toJson" ( fun () ->
                    """{"data":[{"type":"bar","name":"old","x":["Product A","Product B","Product C"],"y":[20,14,23],"orientation":"v","marker":{"pattern":{}}},{"type":"bar","name":"new","x":["Product A","Product B","Product C"],"y":[8,21,13],"orientation":"v","marker":{"pattern":{}}}],"layout":{"barmode":"stack"},"config":{}}"""
                    |> jsonIs StackedColumn.``Two stacked columns chart``
                )
                testCase "Stacked column toFigureJson" ( fun () ->
                    """{"data":[{"type":"bar","name":"old","x":["Product A","Product B","Product C"],"y":[20,14,23],"orientation":"v","marker":{"pattern":{}}},{"type":"bar","name":"new","x":["Product A","Product B","Product C"],"y":[8,21,13],"orientation":"v","marker":{"pattern":{}}}],"layout":{"barmode":"stack"},"frames":[]}"""
                    |> figureJsonIs StackedColumn.``Two stacked columns chart``
                );
            ]
        ]

module Histogram =
    [<Tests>]
    let ``Histogram chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Histogram" [
                
            ]
        ]

module Histogram2D =
    [<Tests>]
    let ``Histogram2D chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Histogram2D" [
                
            ]
        ]

module BoxPlot =
    [<Tests>]
    let ``BoxPlot chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "BoxPlot" [
                testCase "Box1 toJson" ( fun () ->
                    """{"data":[{"type":"box","x":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{},"boxpoints":"all","jitter":0.1}],"layout":{},"config":{}}"""
                    |> jsonIs BoxPlot.``Simple boxplot with boxpoints``
                )
                testCase "Box1 toFigureJson" ( fun () ->
                    """{"data":[{"type":"box","x":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{},"boxpoints":"all","jitter":0.1}],"layout":{},"frames":[]}"""
                    |> figureJsonIs BoxPlot.``Simple boxplot with boxpoints``
                );
                testCase "Box2 toJson" ( fun () ->
                    """{"data":[{"type":"box","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"y":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"orientation":"h","marker":{},"line":{},"boxpoints":"all","jitter":0.1}],"layout":{},"config":{}}"""
                    |> jsonIs BoxPlot.``Simple horizontal boxplot with boxpoints``
                )
                testCase "Box2 toFigureJson" ( fun () ->
                    """{"data":[{"type":"box","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"y":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"orientation":"h","marker":{},"line":{},"boxpoints":"all","jitter":0.1}],"layout":{},"frames":[]}"""
                    |> figureJsonIs BoxPlot.``Simple horizontal boxplot with boxpoints``
                );
                testCase "Box3 toJson" ( fun () ->
                    """{"data":[{"type":"box","name":"bin1","marker":{},"line":{},"boxpoints":"all","jitter":0.1,"x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]},{"type":"box","name":"bin2","marker":{},"line":{},"boxpoints":"all","jitter":0.1,"x":[2.0,1.5,5.0,1.5,2.0,2.5,2.1,2.5,1.5,1.0,2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]}],"layout":{},"config":{}}"""
                    |> jsonIs BoxPlot.``Combined chart with 2 horizontal boxplots``
                )
                testCase "Box3 toFigureJson" ( fun () ->
                    """{"data":[{"type":"box","name":"bin1","marker":{},"line":{},"boxpoints":"all","jitter":0.1,"x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]},{"type":"box","name":"bin2","marker":{},"line":{},"boxpoints":"all","jitter":0.1,"x":[2.0,1.5,5.0,1.5,2.0,2.5,2.1,2.5,1.5,1.0,2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]}],"layout":{},"frames":[]}"""
                    |> figureJsonIs BoxPlot.``Combined chart with 2 horizontal boxplots``
                );
            ]
        ]

module Violin =
    [<Tests>]
    let ``Violin chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Violin" [
                testCase "Violin1 toJson" ( fun () ->
                    """{"data":[{"type":"violin","x":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{},"box":{},"points":"all"}],"layout":{},"config":{}}"""
                    |> jsonIs Violin.``Simple violin plot with jitterpoints``
                )
                testCase "Violin1 toFigureJson" ( fun () ->
                    """{"data":[{"type":"violin","x":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"y":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"marker":{},"line":{},"box":{},"points":"all"}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Violin.``Simple violin plot with jitterpoints``
                );
                testCase "Violin2 toJson" ( fun () ->
                    """{"data":[{"type":"violin","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"y":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"orientation":"h","marker":{},"line":{},"box":{},"jitter":0.1,"meanline":{"visible":true},"points":"all"}],"layout":{},"config":{}}"""
                    |> jsonIs Violin.``Simple horizontal violin plot with jitterpoints``
                )
                testCase "Violin2 toFigureJson" ( fun () ->
                    """{"data":[{"type":"violin","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0],"y":["bin1","bin2","bin1","bin2","bin1","bin2","bin1","bin1","bin2","bin1"],"orientation":"h","marker":{},"line":{},"box":{},"jitter":0.1,"meanline":{"visible":true},"points":"all"}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Violin.``Simple horizontal violin plot with jitterpoints``
                );
                testCase "Violin3 toJson" ( fun () ->
                    """{"data":[{"type":"violin","name":"bin1","marker":{},"line":{},"box":{},"jitter":0.1,"points":"all","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]},{"type":"violin","name":"bin2","marker":{},"line":{},"box":{},"jitter":0.1,"points":"all","x":[2.0,1.5,5.0,1.5,2.0,2.5,2.1,2.5,1.5,1.0,2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]}],"layout":{},"config":{}}"""
                    |> jsonIs Violin.``Combined chart with 2 horizontal violin plots``
                )
                testCase "Violin3 toFigureJson" ( fun () ->
                    """{"data":[{"type":"violin","name":"bin1","marker":{},"line":{},"box":{},"jitter":0.1,"points":"all","x":[2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]},{"type":"violin","name":"bin2","marker":{},"line":{},"box":{},"jitter":0.1,"points":"all","x":[2.0,1.5,5.0,1.5,2.0,2.5,2.1,2.5,1.5,1.0,2.0,1.5,5.0,1.5,3.0,2.5,2.5,1.5,3.5,1.0]}],"layout":{},"frames":[]}"""
                    |> figureJsonIs Violin.``Combined chart with 2 horizontal violin plots``
                );
            ]
        ]

module Histogram2DContour =
    [<Tests>]
    let ``Histogram2DContour chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Histogram2DContour" [
            ]
        ]

module Heatmap =
    [<Tests>]
    let ``Heatmap chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Heatmap" [
                testCase "Heatmap toJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["Tp0","Tp30","Tp60","Tp160"],"y":["p3","p2","p1"],"z":[[1.0,1.5,0.7,2.7],[2.0,0.5,1.2,1.4],[0.1,2.6,2.4,3.0]],"colorscale":[[0.0,"#3D9970"],[1.0,"#001f3f"]],"showscale":true}],"layout":{"width":700,"height":500,"margin":{"l":200.0}},"config":{}}"""
                    |> jsonIs Heatmap.``simple heatmap with custom colorscale``
                )
                testCase "Heatmap toFigureJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["Tp0","Tp30","Tp60","Tp160"],"y":["p3","p2","p1"],"z":[[1.0,1.5,0.7,2.7],[2.0,0.5,1.2,1.4],[0.1,2.6,2.4,3.0]],"colorscale":[[0.0,"#3D9970"],[1.0,"#001f3f"]],"showscale":true}],"layout":{"width":700,"height":500,"margin":{"l":200.0}},"frames":[]}"""
                    |> figureJsonIs Heatmap.``simple heatmap with custom colorscale``
                );
                testCase "Heatmap styled toJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["Tp0","Tp30","Tp60","Tp160"],"y":["p3","p2","p1"],"z":[[1.0,1.5,0.7,2.7],[2.0,0.5,1.2,1.4],[0.1,2.6,2.4,3.0]],"colorscale":[[0.0,"#3D9970"],[1.0,"#001f3f"]],"showscale":true,"colorbar":{"title":{"text":"Im the Colorbar"}}}],"layout":{"width":700,"height":500,"margin":{"l":200.0}},"config":{}}"""
                    |> jsonIs Heatmap.``Simple heatmap with custom colorscale and styled colorbar``
                )
                testCase "Heatmap styled toFigureJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["Tp0","Tp30","Tp60","Tp160"],"y":["p3","p2","p1"],"z":[[1.0,1.5,0.7,2.7],[2.0,0.5,1.2,1.4],[0.1,2.6,2.4,3.0]],"colorscale":[[0.0,"#3D9970"],[1.0,"#001f3f"]],"showscale":true,"colorbar":{"title":{"text":"Im the Colorbar"}}}],"layout":{"width":700,"height":500,"margin":{"l":200.0}},"frames":[]}"""
                    |> figureJsonIs Heatmap.``Simple heatmap with custom colorscale and styled colorbar``
                );
            ]
        ]

module AnnotatedHeatmap =
    [<Tests>]
    let ``AnnotatedHeatmap chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "AnnotatedHeatmap" [
                testCase "Annotated heatmap toJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["C1","C2","C3"],"y":["R1","R2","R3"],"z":[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]}],"layout":{"yaxis":{"autorange":"reversed"},"annotations":[{"x":0,"y":0,"showarrow":false,"text":"1,1"},{"x":1,"y":0,"showarrow":false,"text":"1,2"},{"x":2,"y":0,"showarrow":false,"text":"1,3"},{"x":0,"y":1,"showarrow":false,"text":"2,1"},{"x":1,"y":1,"showarrow":false,"text":"2,2"},{"x":2,"y":1,"showarrow":false,"text":"2,3"},{"x":0,"y":2,"showarrow":false,"text":"3,1"},{"x":1,"y":2,"showarrow":false,"text":"3,2"},{"x":2,"y":2,"showarrow":false,"text":"3,3"}]},"config":{}}"""
                   |> jsonIs AnnotatedHeatmap.``Simple annotated heatmap``
                )
                testCase "Annotated heatmap toFigureJson" ( fun () ->
                    """{"data":[{"type":"heatmap","x":["C1","C2","C3"],"y":["R1","R2","R3"],"z":[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]}],"layout":{"yaxis":{"autorange":"reversed"},"annotations":[{"x":0,"y":0,"showarrow":false,"text":"1,1"},{"x":1,"y":0,"showarrow":false,"text":"1,2"},{"x":2,"y":0,"showarrow":false,"text":"1,3"},{"x":0,"y":1,"showarrow":false,"text":"2,1"},{"x":1,"y":1,"showarrow":false,"text":"2,2"},{"x":2,"y":1,"showarrow":false,"text":"2,3"},{"x":0,"y":2,"showarrow":false,"text":"3,1"},{"x":1,"y":2,"showarrow":false,"text":"3,2"},{"x":2,"y":2,"showarrow":false,"text":"3,3"}]},"frames":[]}"""
                    |> figureJsonIs AnnotatedHeatmap.``Simple annotated heatmap``
                );
            ]
        ]

module Image =
    [<Tests>]
    let ``Image chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Image" [
                testCase "Image raw toJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[0,0,255],[255,255,0],[0,0,255]],[[255,0,0],[255,0,255],[255,0,255]],[[0,255,0],[0,255,255],[255,0,0]]]}],"layout":{"title":{"text":"Image chart from raw color component arrays"}},"config":{}}"""
                   |> jsonIs Image.``Raw color component image chart``
                )
                testCase "Image raw toFigureJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[0,0,255],[255,255,0],[0,0,255]],[[255,0,0],[255,0,255],[255,0,255]],[[0,255,0],[0,255,255],[255,0,0]]]}],"layout":{"title":{"text":"Image chart from raw color component arrays"}},"frames":[]}"""
                    |> figureJsonIs Image.``Raw color component image chart``
                );        
                testCase "Image raw hsl toJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[0,0,255],[255,255,0],[0,0,255]],[[255,0,0],[255,0,255],[255,0,255]],[[0,255,0],[0,255,255],[255,0,0]]],"colormodel":"hsl"}],"layout":{"title":{"text":"HSL color model"}},"config":{}}"""
                   |> jsonIs Image.``HSL image chart``
                )
                testCase "Image raw hsl toFigureJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[0,0,255],[255,255,0],[0,0,255]],[[255,0,0],[255,0,255],[255,0,255]],[[0,255,0],[0,255,255],[255,0,0]]],"colormodel":"hsl"}],"layout":{"title":{"text":"HSL color model"}},"frames":[]}"""
                    |> figureJsonIs Image.``HSL image chart``
                );        
                testCase "Image ARGB toJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[240,248,255,255],[255,248,220,255],[255,240,245,255]],[[169,169,169,255],[255,250,250,255],[25,25,112,255]],[[176,196,222,255],[189,183,107,255],[135,206,250,255]]],"colormodel":"rgba"}],"layout":{"title":{"text":"ARGB image chart"}},"config":{}}"""
                   |> jsonIs Image.``ARGB image chart``
                )
                testCase "Image ARGB toFigureJson" ( fun () ->
                    """{"data":[{"type":"image","z":[[[240,248,255,255],[255,248,220,255],[255,240,245,255]],[[169,169,169,255],[255,250,250,255],[25,25,112,255]],[[176,196,222,255],[189,183,107,255],[135,206,250,255]]],"colormodel":"rgba"}],"layout":{"title":{"text":"ARGB image chart"}},"frames":[]}"""
                    |> figureJsonIs Image.``ARGB image chart``
                );        

                testCase "Image base64 toJson" ( fun () ->
                    """{"data":[{"type":"image","source":""}],"layout":{"title":{"text":"This is Plotly.NET:"}},"config":{}}"""
                    |> jsonIs Image.``Image chart from base64 string``
                )
                testCase "Image base64 toFigureJson" ( fun () ->
                    """{"data":[{"type":"image","source":""}],"layout":{"title":{"text":"This is Plotly.NET:"}},"frames":[]}"""
                    |> figureJsonIs Image.``Image chart from base64 string``
                );        
            ]
        ]

module Contour =
    [<Tests>]
    let ``Contour chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Contour" [
            ]
        ]

module OHLC =
    [<Tests>]
    let ``OHLC chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "OHLC" [
                testCase "simple OHLC toJson" ( fun () ->
                    """{"data":[{"type":"ohlc","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"yaxis":{}}}},"config":{}}"""
                   |> jsonIs OHLC.``Simple OHLC chart``
                )
                testCase "simple OHLC toFigureJson" ( fun () ->
                    """{"data":[{"type":"ohlc","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"yaxis":{}}}},"frames":[]}"""
                   |> figureJsonIs OHLC.``Simple OHLC chart``
                );
                testCase "OHLC no range slider toJson" ( fun () ->
                    """{"data":[{"type":"ohlc","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"visible":false,"yaxis":{}}}},"config":{}}"""
                   |> jsonIs OHLC.``Simple OHLC chart without range slider``
                )
                testCase "OHLC no range slider toFigureJson" ( fun () ->
                    """{"data":[{"type":"ohlc","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"visible":false,"yaxis":{}}}},"frames":[]}"""
                   |> figureJsonIs OHLC.``Simple OHLC chart without range slider``
                );
            ]
        ]

module Candlestick =
    [<Tests>]
    let ``Candlestick chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Candlestick" [
                testCase "simple Candlestick toJson" ( fun () ->
                    """{"data":[{"type":"candlestick","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"yaxis":{}}}},"config":{}}"""
                   |> jsonIs Candlestick.``Simple candlestick chart``
                )
                testCase "simple Candlestick toFigureJson" ( fun () ->
                   """{"data":[{"type":"candlestick","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"yaxis":{}}}},"frames":[]}"""
                   |> figureJsonIs Candlestick.``Simple candlestick chart``
                );
                testCase "Candlestick no range slider toJson" ( fun () ->
                    """{"data":[{"type":"candlestick","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"visible":false,"yaxis":{}}}},"config":{}}"""
                   |> jsonIs Candlestick.``Simple candlestick chart without range slider``
                )
                testCase "Candlestick no range slider toFigureJson" ( fun () ->
                   """{"data":[{"type":"candlestick","x":["2020-01-17T13:40:00","2020-01-17T13:41:00","2020-01-17T13:42:00","2020-01-17T13:43:00","2020-01-17T13:44:00","2020-01-17T13:45:00","2020-01-17T13:46:00","2020-01-17T13:47:00","2020-01-17T13:48:00","2020-01-17T13:49:00","2020-01-17T13:50:00"],"close":[0.6888,0.68877,0.68886,0.68879,0.68874,0.68868,0.68883,0.68899,0.68889,0.68893,0.68891],"open":[0.68888,0.68883,0.68878,0.68886,0.68879,0.68875,0.68869,0.68883,0.68898,0.68889,0.68891],"high":[0.68888,0.68884,0.68889,0.68886,0.68879,0.68877,0.68887,0.68899,0.689,0.68893,0.68896],"low":[0.68879,0.68875,0.68878,0.68876,0.68873,0.68867,0.68869,0.68883,0.68885,0.68881,0.68886],"increasing":{"line":{}},"decreasing":{"line":{}}}],"layout":{"xaxis":{"rangeslider":{"visible":false,"yaxis":{}}}},"frames":[]}"""
                   |> figureJsonIs Candlestick.``Simple candlestick chart without range slider``
                );
            ]
        ]

module Splom =
    [<Tests>]
    let ``Splom chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "Splom" [
                testCase "Scatterplot matrix toJson" ( fun () ->
                    """{"data":[{"type":"splom","dimensions":[{"label":"A","values":[1.0,4.0,3.4,0.7],"axis":{}},{"label":"B","values":[3.0,1.5,1.7,2.3],"axis":{}},{"label":"C","values":[2.0,4.0,3.1,5.0],"axis":{}},{"label":"D","values":[4.0,2.0,2.0,4.0],"axis":{}}],"marker":{"color":"blue"},"diagonal":{}}],"layout":{},"config":{}}"""
                   |> jsonIs Splom.``Simple scatterplot matrix``
                )
                testCase "Scatterplot matrix toFigureJson" ( fun () ->
                   """{"data":[{"type":"splom","dimensions":[{"label":"A","values":[1.0,4.0,3.4,0.7],"axis":{}},{"label":"B","values":[3.0,1.5,1.7,2.3],"axis":{}},{"label":"C","values":[2.0,4.0,3.1,5.0],"axis":{}},{"label":"D","values":[4.0,2.0,2.0,4.0],"axis":{}}],"marker":{"color":"blue"},"diagonal":{}}],"layout":{},"frames":[]}"""
                   |> figureJsonIs Splom.``Simple scatterplot matrix``
                )
            ]
        ]

module PointDensity =
    [<Tests>]
    let ``PointDensity chart HTML codegeneration tests`` =
        testList "JSONGen.Chart2D" [
            testList "PointDensity" [
                testCase "PointDensity toJson" ( fun () ->
                    """{"data":[{"type":"histogram2dcontour","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"line":{"width":0.0},"contours":{"coloring":"fill"}},{"type":"scatter","opacity":0.3,"mode":"markers","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"marker":{}}],"layout":{},"config":{}}"""
                    |> jsonIs PointDensity.``Simple PointDensity chart``
                )
                testCase "PointDensity toFigureJson" ( fun () ->
                    """{"data":[{"type":"histogram2dcontour","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"line":{"width":0.0},"contours":{"coloring":"fill"}},{"type":"scatter","opacity":0.3,"mode":"markers","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"marker":{}}],"layout":{},"frames":[]}"""
                    |> figureJsonIs PointDensity.``Simple PointDensity chart``
                )
                testCase "PointDensity styled toJson" ( fun () ->
                    """{"data":[{"type":"histogram2dcontour","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"line":{"width":0.0},"colorbar":{"title":{"text":"Density"}},"colorscale":"Viridis","contours":{"coloring":"fill","showlabels":true}},{"type":"scatter","opacity":0.3,"mode":"markers","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"marker":{"color":"rgba(128, 0, 128, 1.0)","size":4,"symbol":"4"}}],"layout":{},"config":{}}"""
                    |> jsonIs PointDensity.``Styled PointDensity chart``
                )
                testCase "PointDensity styled toFigureJson" ( fun () ->
                   """{"data":[{"type":"histogram2dcontour","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"line":{"width":0.0},"colorbar":{"title":{"text":"Density"}},"colorscale":"Viridis","contours":{"coloring":"fill","showlabels":true}},{"type":"scatter","opacity":0.3,"mode":"markers","x":[0.33836984091362443,0.2844184475412678,0.2629626417825756,0.6253758443637638,0.46346185284827923,0.9283738280312968,0.1463105539541275,0.9505998873853124,0.5961332552116985,0.11745994590104555,0.975558924477342,0.37088692624628866,0.0699143670824889,0.07078822472635109,0.48201058175508427,0.15297147219673332,0.9641655045394625,0.09534371648698287,0.8125330809562156,0.2506162050415837,0.48126059979259067,0.07473527084790882,0.8369272271343168,0.7793545950107996,0.18997055114711195,0.7421991949631829,0.2328434778530353,0.7856600809775572,0.9278804142623583,0.10790790343094053,0.03301328235911824,0.770361295794305,0.30779169793603556,0.11389689665003536,0.388590590743623,0.9796536713743832,0.17214082375734152,0.7884985966554371,0.1994013894346549,0.7964705586416976,0.3436089406458703,0.10509170037931376,0.9796912223006092,0.8392714871276503,0.5432778380547081,0.1979652751227679,0.038267011306372944,0.5355382620056803,0.6352935864754456,0.8821615948724382,0.9909701128448221,0.9722291035448336,0.2536179266188377,0.5066026125599642,0.19606175189654423,0.2636345700657156,0.447491220406951,0.48360804677177593,0.4354052932166519,0.7212626578850964,0.6955303501782615,0.3606504729765702,0.022719473122954123,0.48822535178075793,0.08444666354192731,0.20519762868303695,0.06309522831025312,0.9560174704324536,0.682197633982728,0.5023569103807011,0.9808306484393918,0.17566690788402545,0.8959423270523279,0.016062522314518,0.9070072643957134,0.37616889941327686,0.0950440485472996,0.9976557400066665,0.2360767569560915,0.9920052760243441,0.70393218365681,0.6973052158473549,0.15036649450211156,0.04571881938992013,0.11693779058611849,0.060784178814284585,0.5167433691754674,0.8011890853760714,0.9178351447534912,0.1249560206779074,0.5321624509674322,0.6885327769855656,0.35309330343878514,0.47813873154955855,0.10094020846343608,0.9829584676693001,0.08237222725635963,0.4914658705198513,0.754824823585723,0.33808020937167116,0.1348700468125148],"y":[0.0822495408739194,0.8533406280229523,0.13293667609474466,0.9013309464330463,0.8153032049607966,0.07628677649250569,0.2375554043043197,0.5995953481642508,0.8198928524832674,0.16859052151841603,0.44983548040028454,0.24753128981568445,0.44340001719230787,0.017330474228286406,0.9982251343309065,0.21028397847445868,0.977000653733034,0.37128756119463946,0.023662484727642725,0.6884542595075696,0.2619061429341818,0.03818232567896243,0.5572416133048207,0.9701944594132688,0.29229787145382624,0.8225736044452403,0.4178035955027694,0.9151223138510819,0.9240487967264135,0.29379667215691724,0.6035781780274483,0.24283091642094354,0.8979965475844204,0.8571352292118293,0.6216826427828905,0.8439645878244026,0.0174298184073669,0.1443878729568738,0.30163458562532186,0.9844974023217788,0.2791879648711476,0.20159373721182056,0.09794229227022375,0.9563654991594914,0.0823269705671477,0.44100148716988113,0.9096932862464773,0.4608082573212722,0.10271507413252959,0.7726744891948414,0.10537157352332564,0.12017830932521183,0.7311623388580802,0.6496259498641016,0.872963903878333,0.04406721519495697,0.29609901471813166,0.16274221668147584,0.6090330749792201,0.9927296005155564,0.6584831809897363,0.3224330904532378,0.6755465514378374,0.5260961803263501,0.5650123434909677,0.20700456397934097,0.34953474223126413,0.5862647879804787,0.3956478314453959,0.15426054650650387,0.19285416006709177,0.8326127807761602,0.06965297556931757,0.03916508240586383,0.409266294636422,0.06031240572236125,0.9402400334087387,0.6008761141453293,0.8878674888461211,0.8512963842839452,0.912880318198763,0.9569953381814972,0.8124072397185523,0.15137430753157208,0.1884250986335916,0.4833998687022365,0.5116685775628633,0.24837059772031875,0.9841713253334963,0.5776154275879336,0.547865573106271,0.8546876017258911,0.5353547979776537,0.30890498510976555,0.3260142213320426,0.9567548744179099,0.5260471857739832,0.5718461119438736,0.3913531556685237,0.8753224065878067,0.09146674493861699],"marker":{"color":"rgba(128, 0, 128, 1.0)","size":4,"symbol":"4"}}],"layout":{},"frames":[]}"""
                   |> figureJsonIs PointDensity.``Styled PointDensity chart``
                )
            ]
        ]

